from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError

import app00.models
from django.conf import settings
import random

from app00 import models
from app00.forms.bootstrap import BootStrap


class RegisterModelForm(BootStrap, forms.ModelForm):

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request
        # # name：字段名称 field：类型对象（CharField（））
        # for name, field in self.fields.items():
        #     field.widget.attrs['class'] = 'form-control'
        #     field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)

    # 添加正则表达式的校验
    mobile_phone = forms.CharField(label='手机号',
                                   # 第一个参数为正则表达式 ，第二个参数为报错信息
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    # 修改密码的默认显示
    password = forms.CharField(
        label='密码',
        # 设置插件：使用密文的方式进行显示 attrs={'class': 'form-control'}在生成表单的时候直接加上class样式
        # widget=forms.PasswordInput(attrs={'class': 'form-control'})
        widget=forms.PasswordInput(),

        # 设置最大最小以及错误信息提示
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': "密码长度不能小于8个字符",
            'max_length': "密码长度不能大于64个字符"
        },

    )

    # 在数据库中不需要保存确认密码字段，需要自定义字段信息
    confirm_password = forms.CharField(
        label='重复密码',
        widget=forms.PasswordInput(),
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': "重复密码长度不能小于8个字符",
            'max_length': "重复密码长度不能大于64个字符"
        },
    )

    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())

    # 使用钩子函数校验表单信息
    def clean_username(self):
        username = self.cleaned_data['username']
        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户名已存在')
            # self.add_error('username','用户名已存在')
        return username

    def clean_email(self):
        email = self.cleaned_data['email']
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('邮箱已存在')
        return email

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密 & 返回
        # return encrypt.md5(pwd)
        return pwd

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get('password')

        # 加密操作
        # confirm_pwd = encrypt.md5(self.cleaned_data['confirm_password'])
        confirm_pwd = self.cleaned_data['confirm_password']

        if pwd != confirm_pwd:
            raise ValidationError('两次密码不一致')

        return confirm_pwd

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已注册')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']

        # mobile_phone = self.cleaned_data['mobile_phone']

        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not mobile_phone:
            return code

        # conn = get_redis_connection()
        # redis_code = conn.get(mobile_phone)
        redis_code = self.request.session.get('code')  # 从session中获取验证码
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        # redis_str_code = redis_code.decode('utf-8')

        # if code.strip() != redis_code:
        if code != redis_code:
            raise ValidationError('验证码错误，请重新输入')

        return code

    class Meta:
        model = models.UserInfo
        # 生成所有字段
        # fields = '__all__'
        # 选择要生成表单的字段和顺序
        fields = ['username', 'email', 'password', 'confirm_password', 'mobile_phone', 'code']


class SendSmsForm(forms.Form):
    """发送短信表单验证"""
    mobile_phone = forms.CharField(
        label='手机号',
        validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式不正确'), ]
    )

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']

        # 判断模版是否存在
        tpl = self.request.GET.get('tpl')
        template_id = settings.TENCENT_SMS_TEMPLATE.get(tpl)
        if not template_id:
            raise ValidationError('模版不存在')
        # 手机号是否存在
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if tpl == 'login':
            if not exists:
                raise ValidationError('手机号不存在')
        else:
            if exists:
                raise ValidationError('手机已存在')
        # 生成验证码
        code = random.randrange(1000, 9999)
        print("验证码：" + str(code))

        self.request.session['code'] = str(code)
        self.request.session.set_expiry(60)

        return mobile_phone


class loginSmsForm(BootStrap, forms.Form):
    """短信登录表单"""
    mobile_phone = forms.CharField(
        label='手机号',
        validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式不正确'), ]
    )

    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if not exists:
            raise ValidationError('手机号不存在')

        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']
        mobile_phone = self.cleaned_data.get('mobile_phone')

        # 手机号不存在，则验证码无需再校验
        if not mobile_phone:
            return code

        session_code = self.request.session['code']  # 从session中获取验证码
        if not session_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        if code != session_code:
            raise ValidationError('验证码错误，请重新输入')

        return code


class loginForm(BootStrap, forms.Form):
    username = forms.CharField(label='邮箱或手机号')
    password = forms.CharField(
        label='密码',
        widget=forms.PasswordInput(render_value=True)
    )
    code = forms.CharField(label='图片验证码')

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_code(self):
        code = self.cleaned_data['code']
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码已过期，请重新输入')

        if code.strip().upper() != session_code.upper():
            raise ValidationError('验证码输入有误')
        return code
